package com.dtx.day5.day5Field;

import com.dtx.day1.entity.Goods;
import org.junit.Test;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 获取属性Field
 */
public class TestField2 {

    public <T> T mapToObj(Map<String,Object> map,Class<T> clz) throws Exception {
        //通过 clz 创建一个对象
        T obj = clz.getDeclaredConstructor().newInstance();

        // 获取 该 对象中的所有属性
        Field[] fields = clz.getDeclaredFields();

        //遍历 Map，将 Map中所有的键 设置到 对应了 类的属性上
        map.forEach((key,value) -> {

            // 查找 数组中 field 属性 名 和 key 相同的属性，并给他 设置值
        try {
            Optional<Field> optional = Arrays.stream(fields).filter(f -> key.equals(f.getName())).findFirst();

            if (optional.isPresent()) {

                // 将 找到的 属性 值 设置为 Value
                Field field = optional.get();

                //设置允许访问 受保护的资源
                field.setAccessible(true);
                field.set(obj, converter(value,field.getType()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        });

        return obj;
    }

    private Object converter(Object value,Class<?> type){

        if (value == null) return null;

        //获取数据的类型
        Class<?> real = value.getClass();

        if (real != type) {
            throw new RuntimeException("类型转型失败,期待的数据类型是"+type.getName()+", 实际获取的是"+value.getClass().getName());
        }

       return value;

    }

    @Test
    public void mapToObj() throws Exception{
        /**
         * 通过 反射 ， 将 map 对象中的所有数据，转成，指定的一个对象
         *
         */
        Map<String,Object> map = new HashMap<>();

        map.put("num","0001");
        map.put("goodsName","键盘");
        map.put("goodsDesc","机械键盘，手感非常不错");
        map.put("goodsPrice",new BigDecimal("200"));
        map.put("createTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2001-11-12 11:33:33"));

        Goods goods = mapToObj(map, Goods.class);

        System.out.println(goods);
    }


}
